import html2canvas from 'html2canvas';
import { isIE } from '../utils/index';

const printMixin = {
  data() {
    return {
      printAreaPrinting: false
    };
  },
  methods: {
    /**
     * 传入指定区域元素ref打印页面内容
     * @param refId 指定打印区域元素的ref属性值
     * @param childrenCls 指定区域元素内部子元素的样式设置，如：{ className: { background: 'transparent' }}
     * @param printWidth 指定区域打印宽度，默认为1245，单位为px
     * @param styleObj 打印区域样式设置，如：{ width: '1000px', color: 'red' }
     */
    print(refId, childrenCls, printWidth = 1245, styleObj) {
      this.setColumnsNotEllipsis(refId);
      this.setPrintAreaWidth(refId, printWidth);
      if (isIE) {
        this.calcZoom(refId);
      }
      this[refId + 'Printing'] = true;
      setTimeout(() => {
        this.printPreview(
          refId,
          isIE ? this.zoom : '',
          () => {
            this.setColumnsEllipsis(refId);
          },
          childrenCls,
          styleObj
        );
        this[refId + 'Printing'] = false;
      }, 2500);
    },
    setPrintAreaWidth(refId, printWidth) {
      const printEle = this.$refs[refId]._isVue
        ? this.$refs[refId].$el
        : this.$refs[refId];
      let printAreaWidth = parseInt(
        window.getComputedStyle(printEle).width,
        10
      );
      if (printAreaWidth < printWidth) {
        printAreaWidth = printWidth;
      }
      this[refId + 'Width'] = printAreaWidth + 'px';
    },
    calcZoom(refId) {
      const printAreaWidth = parseInt(this[refId + 'Width'], 10);
      if (printAreaWidth < 1756) {
        this.zoom = '100%';
      } else {
        this.zoom = Math.floor((1756 / printAreaWidth) * 100) + '%';
      }
    },
    setColumnsNotEllipsis(refId) {
      this.changeColumnsClass(refId, 'elp-ellipsis', '___elp-ellipsis');
    },
    setColumnsEllipsis(refId) {
      this.changeColumnsClass(refId, '___elp-ellipsis', 'elp-ellipsis');
    },
    changeColumnsClass(refId, oldClass, newClass) {
      const toPrint = refId ? this.$refs[refId] : document.body;
      const toPrintEle = toPrint._isVue ? toPrint.$el : toPrint;
      let overflowCollect = toPrintEle.querySelectorAll(`.${oldClass}`);
      for (let i = 0; i < overflowCollect.length; i++) {
        const classes = overflowCollect[i].getAttribute('class').split(' ');
        const ellipsisIndex = classes.indexOf(oldClass);
        if (ellipsisIndex > -1) {
          classes[ellipsisIndex] = newClass;
          overflowCollect.setAttribute('class', classes.join(' '));
        }
      }
    },
    IEPrint(callback) {
      const webBrowserObj = document.createElement('object');
      webBrowserObj.id = 'WebBrowser';
      webBrowserObj.classid = 'CLSID:8856F961-340A-11D0-A96B-00C04FD705A2';
      webBrowserObj.height = '0';
      webBrowserObj.width = '0';
      webBrowserObj.VIEWASTEXT = true;
      document.body.appendChild(webBrowserObj);

      setTimeout(() => {
        window.WebBrowser.execwb(7, 1); // 打印预览
        setTimeout(() => {
          callback();
          document.body.removeChild(webBrowserObj);
        }, 2500);
      });
    },
    /**
     * 传入指定区域元素id打印页面内容
     * @param refId 指定打印区域元素的ref属性值
     * @param zoom 打印区域缩放比例，如：'80%'
     * @param callback 打印后回调函数
     * @param childrenCls 指定区域元素内部子元素的样式设置，如：{ className: { background: 'transparent' }}
     * @param styleObj 打印区域样式设置，如：{ width: '1000px', color: 'red' }
     */
    printPreview(
      refId = 'printArea',
      zoom,
      callback,
      childrenCls = {},
      styleObj = {
        padding: isIE ? '0 18px 0px 32px' : '',
        'box-sizing': 'content-box'
      }
    ) {
      window.scroll(0, 0);
      const toPrintEle = this.$refs[refId].$el || this.$refs[refId];
      const printArea = toPrintEle.cloneNode(true);
      const toPrintEleCanvasArr = toPrintEle.querySelectorAll('canvas');
      const printAreaCanvasArr = printArea.querySelectorAll('canvas');
      let index = 0;
      for (let printAreaCanvas of printAreaCanvasArr) {
        const img = new Image();
        img.src = toPrintEleCanvasArr[index].toDataURL('image/png');
        img.width = 1122;
        img.style.padding = '0 32px 0 32px';
        printAreaCanvas.parentNode.insertBefore(img, printAreaCanvas);
        printAreaCanvas.parentNode.removeChild(printAreaCanvas);
        index++;
      }
      printArea.style.width = this[refId + 'Width'];
      // 设置缩放
      if (isIE && zoom) {
        const oldStyle = printArea.getAttribute('style') || '';
        printArea.setAttribute('style', oldStyle + 'zoom: ' + zoom + ';');
      }

      // 打印区域样式设置
      Object.keys(styleObj).forEach(key => {
        const oldStyle = printArea.getAttribute('style');
        printArea.setAttribute(
          'style',
          oldStyle + key + ': ' + styleObj[key] + ';'
        );
      });

      // 解决打印input显示空白问题
      const inputArr = document.getElementsByTagName('input');
      for (let i = 0; i < inputArr.length; i++) {
        inputArr[i].setAttribute('value', inputArr[i].value);
      }

      // 打印时缓存元素display状态并隐藏所有元素
      let displayArr = [];
      for (let i = 0; i < document.body.children.length; i++) {
        displayArr.push(document.body.children[i].style.display + '');
        document.body.children[i].style.display = 'none';
      }

      // 添加需要打印元素的拷贝到DOM
      const printDiv = document.createElement('div');
      printDiv.id = '___print-dom';
      printDiv.appendChild(printArea);
      document.body.appendChild(printDiv);
      // 指定区域元素内部子元素的样式设置
      Object.keys(childrenCls).forEach(className => {
        const attr = childrenCls[className];
        Object.keys(attr).forEach(cssName => {
          document
            .querySelectorAll('#___print-dom .' + className)
            .forEach(ele => {
              ele.style[cssName] = attr[cssName];
            });
        });
      });

      const afterPrintCallback = img => {
        document.body.removeChild(printDiv);
        if (img) {
          if (img instanceof Array) {
            for (let image of img) {
              document.body.removeChild(image);
            }
          } else {
            document.body.removeChild(img);
          }
        }

        for (let i = 0; i < document.body.children.length; i++) {
          document.body.children[i].style.display = displayArr[i];
        }
        displayArr = [];

        window.scroll(0, 0);
        if (callback) {
          callback();
        }
      };

      if (isIE) {
        this.IEPrint(afterPrintCallback);
      } else {
        setTimeout(() => {
          html2canvas(printArea).then(canvas => {
            const img = new Image();
            img.src = canvas.toDataURL('image/png');
            img.width = 1122;
            img.style.padding = '0 32px 0 32px';
            document.body.appendChild(img);
            printDiv.style.display = 'none';
            setTimeout(() => {
              window.print();
              afterPrintCallback(img);
            }, 2500);
          });
        }, 200);
      }
    }
  }
};

export default printMixin;
